#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "quixie_string.h"

typedef struct {
	//KSFile *file_ptr;
	unsigned int line;
	char *value;
} QuixieToken;

typedef struct {
	FILE *file_ptr;
	char *file_content;
	QuixieToken *token;
	unsigned int token_ctr;
} KSFile;

int flen(FILE *flen_file) {
	int size;
	
	fseek(flen_file, 0, SEEK_END);
		size = ftell(flen_file);
	fseek(flen_file, 0, SEEK_SET);
	
	return size;
}

int fget(char **__s, FILE *fget_file) {
	int LOF = flen(fget_file);
	
	*__s = malloc(sizeof(char) * (LOF + 1));
	char *s = *__s;
	int i = 0;
	while (i < LOF) {
		*s++ = fgetc(fget_file);
		i++;
	}
	*s = '\0';
	
	return 0;
}

KSFile *quixie_ksfile_new() {
	return (KSFile *) malloc(sizeof(KSFile));
}

int quixie_ksfile_load(KSFile *ks_file, const char *file_name) {
	ks_file->file_ptr = fopen(file_name, "rb");
	
	if (ks_file->file_ptr != NULL) {
		
		if (fget(&ks_file->file_content, ks_file->file_ptr) == 0) {
			return 0;
		} else {
			return 2;
		}
	} else {
		return 1;
	}
}

int quixie_process_script_parse(KSFile *ks_file) {
	char *sScript;
		sScript = quixie_string_new();
		quixie_string_set(&sScript, ks_file->file_content);
		
		char *sChar;                //for taking each character from user input
		char *sToken;              //for taking each token from user input
		unsigned int iChar;        //for comparing to ascii values of characters
		unsigned int iLine;        //for line counting
		unsigned int iToken;       //for token counting
	//	char **sArrScript[];       //for multiple ".KS" file - script
	//	char **sArrSource[];       //for multiple ".KS" file - filename
		unsigned int i;
		unsigned int iii;
		
		iToken = 0;  //start index at 0 (zero)
		char *tmpChar;
		
		ks_file->token_ctr = (unsigned int) strlen(sScript); //temporarily, set token counter to highest possible count
		ks_file->token = (QuixieToken *) malloc(sizeof(QuixieToken) * ks_file->token_ctr); //then set token array-size on highest possible size
		QuixieToken *tokens = ks_file->token;
		
		int proceed;
		
	//	//========================================================================
	//	//==#the idea is to loop and parse all files w/ ln# and file info ========
	//	//========================================================================
	//	sScript = sScript & kseSOURCE_SEP & kseSCRIPT_MARK & kseSCRIPT_SEP	 'add marker
	//	Split(sScript, kseSOURCE_SEP, sArrSource[])
		iii = 0;
	//	//engine_log "here:" & sScript
	//	do while (Left(sArrSource(iii), Len(kseSCRIPT_MARK)) != kseSCRIPT_MARK) {
	//		Split(sArrSource(iii), kseSCRIPT_SEP, sArrScript[])
	//		AddSourceName(sArrScript[0))
	//		sArrScript[1] = Trim(sArrScript[1])
	//		
		//========================================================================
			iLine = 1;                                         //start line on 1 (one)
			ks_file->token_ctr = (unsigned int) strlen(sScript);   //set token counter to highest possible count
			sChar = quixie_string_new();
			sToken = quixie_string_new();
			tmpChar = quixie_string_new();
			for (i = 0; i <= (unsigned int) strlen(sScript) + 1; i++) {
				sChar = quixie_string_char_at(sScript, sChar, i);
				iChar = sChar[0];
				proceed = 0;
				//check if a-z/A-Z/0-9/[underscore]
				if ((iChar >= 97 && iChar <= 122)
						|| (iChar >= 65 && iChar <= 90)
						|| (iChar >= 48 && iChar <= 57)
						|| iChar == 95) {
					quixie_string_append(&sToken, sChar);    //append (numeric) character to sToken
				} else {
					//printf("in here %s_ at %i\n", sToken, iToken);
					//# Whatever value the sChar is holding store it to token array
					//# This is to token a special character, separately
					//________________________________________________________________
					if (strcmp(sToken, "") != 0) {    //check if stoken in not empty
						tokens[iToken].value = quixie_string_new();
						if (quixie_string_is_numeric(sToken) == 1) {
							quixie_string_set(&tokens[iToken].value, sToken); //if not, put sToken,
							tokens[iToken].line = iLine;                    //line reference,
							//kseToken[iToken].iSrc = iii + 1         //and file reference to token array
							
							iToken = iToken + 1;                      //change index
							quixie_string_set(&sToken, "");   //clear token
						} else if (iChar == 46 && quixie_string_is_numeric(sToken) == 1) {    //is char DOT
							quixie_string_append(&sToken, "."); //then add as decimal point to numeric values
							proceed = 1;
						} else {
							quixie_string_set(&tokens[iToken].value, sToken);
							tokens[iToken].line = iLine;
							
							iToken = iToken + 1;
							//printf("TRY LEARN WHY sToken( %s ) NEEDS REALLOC: SEE LINE 145\n", sToken);
							sToken = quixie_string_new(); //comment this line out to see bug
							quixie_string_set(&sToken, "");
						}
					} else if (iToken > 0) {
						if ((strcmp(tokens[iToken - 1].value, "<") == 0
								|| strcmp(tokens[iToken - 1].value, "!") == 0
								|| strcmp(tokens[iToken - 1].value, "=") == 0
								|| strcmp(tokens[iToken - 1].value, ">") == 0) && iChar == 61) {   //'is char `EQUAL SIGN'
							sChar = strcat(tokens[iToken - 1].value, sChar);
							quixie_string_set(&tokens[iToken - 1].value, " "); //this should be SPACE (try empty string to see the bug)
						}
					}
					
					if (proceed != 1) {
						tokens[iToken].value = quixie_string_new();
						
						//# If the special character is same to vbCrLf, token a [space]
						if (iChar == 13 && i < (int) strlen(sScript)) {
							tmpChar = quixie_string_char_at(sScript, tmpChar, i + 1);
							if (tmpChar[0] == 10) { //10 is vbLF
								i = i + 1;
							} else {
								//Previously, only vbCRLF is being considered as new line.
								//This should let vbCr (Mac line end) alone will be considered too.
							}
							//tokens[iToken]->value = quixie_string_new();
							quixie_string_set(&tokens[iToken].value, " "); //I used SPACE as Token because Quixie
							tokens[iToken].line = iLine;                //will snob it anyway. my purpose is to
																//maintain the integrity of line error once
							iLine = iLine + 1;                  //source code is pseudo-compiled --Mj
						} else if (iChar == 10) { //10 is vbLF -- GNU/Linux line ending
							//added to fix CHR(10) escaping from screening
							quixie_string_set(&tokens[iToken].value, " ");
							tokens[iToken].line = iLine;
							
							iLine = iLine + 1;
						} else {
//							tokens[iToken].value = quixie_string_new();
							quixie_string_set(&tokens[iToken].value, sChar); //if not, put sChar
							tokens[iToken].line = iLine;                 //line reference
							
							quixie_string_set(&sToken, ""); //clear token
						}
						//kseToken[iToken].iSrc = iii + 1;   //and file reference to token array
						
						iToken = iToken + 1;               //change index
					}
				}
			}
			
			// # added to fix logic error in parsing
			if (strcmp(sToken, "") != 0) {    //check if stoken in not empty
				tokens[iToken].value = quixie_string_new();
				quixie_string_set(&tokens[iToken].value, sChar); //if not, put sToken
				tokens[iToken].line = iLine;                   //line reference
				//kseToken[iToken].iSrc = iii + 1;     //file reference to token array
				quixie_string_set(&sToken, "");
				iToken = iToken + 1;                 //change index
			}
		//========================================================================
			iii = iii + 1;
	//	}
	//	//========================================================================
	//	//========================================================================
		ks_file->token_ctr = iToken;   //reset token counter
	//	if (iShowScript == 1 && InStr(1, LCase(sStartScript), ".kh") == 0) {
	//		//SneakScript
	//	}
	//	
	//	//ProcessScript_CheckSyntax
	
	return 0;
}

void quixie_sneak_script(KSFile *ks_file) {
	int i;
	QuixieToken *token;
	
	for (i = 0; i < ks_file->token_ctr; i++) {
		token = &ks_file->token[i];
		printf("%i #%i %s\n", i, token->line, token->value);
	}
}

int main(int argc, char *argv[]) {
	printf("argc %i\n", argc);
	if (argc > 0) {
		printf("argv %s\n", argv[0]);
	}
	KSFile *ksFile;
	ksFile = quixie_ksfile_new();
	int tmp = quixie_ksfile_load(ksFile, "test.ks");
	
	if (tmp == 1) {
		printf("opening file failed");
	} else if (tmp == 2) {
		printf("geting file content failed");
	} else {
		printf("\n~~~~~~~~~\n");
		if (quixie_process_script_parse(ksFile) == 0) {
			quixie_sneak_script(ksFile);
		}
	}
	
	return 0;
}
